package ac.github.oa.api.compat

import ac.github.oa.OriginAttribute
import ac.github.oa.api.event.entity.EntityDropItemEvent
import ac.github.oa.internal.core.item.ItemPlant
import ink.ptms.um.event.MobDeathEvent
import ink.ptms.um.event.MobSpawnEvent
import io.lumine.xikage.mythicmobs.MythicMobs
import org.bukkit.entity.Entity
import org.bukkit.entity.LivingEntity
import org.bukkit.inventory.ItemStack
import taboolib.common.platform.event.OptionalEvent
import taboolib.common.platform.event.SubscribeEvent
import taboolib.common.platform.function.warning
import taboolib.common.util.random
import taboolib.common5.Coerce.*
import taboolib.platform.util.buildItem
import taboolib.type.BukkitEquipment
import java.util.stream.Collectors
import java.util.stream.IntStream

object MythicMobsHook {

    val cache = mutableMapOf<String, Map<String, String>>(
        "{}" to mutableMapOf()
    )

    fun handleDrop(entity: Entity, killer: LivingEntity?, display: String, drops: List<String>): MutableList<ItemStack> {
        val itemStacks = mutableListOf<ItemStack>()
        drops.filter { it.contains(" ") }.forEach { str ->
            val args = str.split(" ")
            val amount = if (args.size > 1) {
                val split = args[1].split("-")
                random(toInteger(split[0]), toInteger(split.getOrElse(1) { split[0] }))
            } else 1
            val chance = toDouble(args.getOrElse(2) { "1" })
            val jsonString = args.getOrElse(3) { "{}" }

            val event = EntityDropItemEvent(killer,entity,args[0], amount, chance)
            event.data += cache.computeIfAbsent(jsonString) {
                OriginAttribute.json.fromJson<Map<String, String>>(jsonString, Map::class.java)
            }
            if (event.call() && random(event.chance)) {
                itemStacks += createItem(event.id,event.amount,display,event.data.toMap())
            }
        }
        return itemStacks

    }

    fun createItem(id: String, amount: Int,display: String,data: Map<String,String>): List<ItemStack> {

        if (id.startsWith("mm:") || id.startsWith("mythic:")) {
            return listOf(buildItem(MythicMobs.inst().itemManager.getItemStack(id.split(":")[1])) {
                this.amount = amount
            })
        }

        if (!ItemPlant.hasKey(id)) {
            warning("MythicMobs - Drop No Item: $display - $id")
            return emptyList()
        }

        return IntStream.range(0,amount).mapToObj { ItemPlant.build(null,id,data.toMutableMap())!! }.collect(Collectors.toList())
    }


    // MythicMob 4
    @SubscribeEvent(bind = "ink.ptms.um.event.MobDeathEvent")
    fun e(ope: OptionalEvent) {
        val event = ope.get<MobDeathEvent>()
        val config = event.mob.config
        event.drop += handleDrop(event.mob.entity, event.killer, config.name, config.getStringList("OriginOptions.Drops"))
    }

    fun handleUpdate(entity: LivingEntity, equipments: List<String>) {
        val equipment = entity.equipment ?: return
        equipments.forEach {
            val split = it.split(" ")
            val key = split[0].uppercase()
            val slot = split[1]
            if (ItemPlant.hasKey(key)) {
                equipment.setItem(BukkitEquipment.valueOf(slot).bukkit, ItemPlant.build(entity, key))
            }
        }

    }

    @SubscribeEvent(bind = "ink.ptms.um.event.MobSpawnEvent")
    fun e1(ope: OptionalEvent) {
        val event = ope.get<MobSpawnEvent>()
        val entity = event.mob.entity as LivingEntity
        handleUpdate(entity, event.mob.config.getStringList("OriginOptions.Equipment"))
    }
}